home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / eprom.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  20KB  |  727 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/eprom.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bits 13-15 = palette
  15.             Bits  0-12 = image number
  16.  
  17.  
  18.     Motion Object encoding
  19.     ----------------------
  20.         4 16-bit words are used
  21.  
  22.         Word 1:
  23.             Bits  0-7  = link to the next motion object
  24.  
  25.         Word 2:
  26.             Bits  0-11 = image index
  27.  
  28.         Word 3:
  29.             Bits  7-15 = horizontal position
  30.             Bits  0-3  = motion object palette
  31.  
  32.         Word 4:
  33.             Bits  7-15 = vertical position
  34.             Bits  4-6  = horizontal size of the object, in tiles
  35.             Bit   3    = horizontal flip
  36.             Bits  0-2  = vertical size of the object, in tiles
  37.  
  38.  
  39.     Alpha layer encoding
  40.     --------------------
  41.         1 16-bit word is used
  42.  
  43.         Word 1:
  44.             Bit  15    = transparent/opaque
  45.             Bit  10-13 = color
  46.             Bits  0-9  = index of the character
  47.  
  48. ***************************************************************************/
  49.  
  50. #include "driver.h"
  51. #include "machine/atarigen.h"
  52. #include "vidhrdw/generic.h"
  53.  
  54. #define XCHARS 42
  55. #define YCHARS 30
  56.  
  57. #define XDIM (XCHARS*8)
  58. #define YDIM (YCHARS*8)
  59.  
  60.  
  61. #define DEBUG_VIDEO 0
  62.  
  63.  
  64.  
  65. /*************************************
  66.  *
  67.  *    Globals we own
  68.  *
  69.  *************************************/
  70.  
  71. UINT8 *eprom_playfieldpalram;
  72. size_t eprom_playfieldpalram_size;
  73.  
  74.  
  75.  
  76. /*************************************
  77.  *
  78.  *    Structures
  79.  *
  80.  *************************************/
  81.  
  82. struct pf_overrender_data
  83. {
  84.     struct osd_bitmap *bitmap;
  85.     int mo_priority;
  86. };
  87.  
  88.  
  89.  
  90. /*************************************
  91.  *
  92.  *    Statics
  93.  *
  94.  *************************************/
  95.  
  96. static struct atarigen_pf_state pf_state;
  97.  
  98. #if DEBUG_VIDEO
  99. static int show_colors;
  100. static int special_pen;
  101. #endif
  102.  
  103.  
  104.  
  105. /*************************************
  106.  *
  107.  *    Prototypes
  108.  *
  109.  *************************************/
  110.  
  111. static const UINT8 *update_palette(void);
  112.  
  113. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  114. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  115. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  116.  
  117. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  118. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  119.  
  120. #if DEBUG_VIDEO
  121. static void debug(void);
  122. #endif
  123.  
  124.  
  125.  
  126. /*************************************
  127.  *
  128.  *    Video system start
  129.  *
  130.  *************************************/
  131.  
  132. int eprom_vh_start(void)
  133. {
  134.     static struct atarigen_mo_desc mo_desc =
  135.     {
  136.         1024,                /* maximum number of MO's */
  137.         8,                   /* number of bytes per MO entry */
  138.         2,                   /* number of bytes between MO words */
  139.         0,                   /* ignore an entry if this word == 0xffff */
  140.         0, 0, 0x3ff,         /* link = (data[linkword] >> linkshift) & linkmask */
  141.         1                    /* reverse order */
  142.     };
  143.  
  144.     static struct atarigen_pf_desc pf_desc =
  145.     {
  146.         8, 8,                /* width/height of each tile */
  147.         64, 64                /* number of tiles in each direction */
  148.     };
  149.  
  150.     /* reset statics */
  151.     memset(&pf_state, 0, sizeof(pf_state));
  152.  
  153.     /* initialize the playfield */
  154.     if (atarigen_pf_init(&pf_desc))
  155.         return 1;
  156.  
  157.     /* initialize the motion objects */
  158.     if (atarigen_mo_init(&mo_desc))
  159.     {
  160.         atarigen_pf_free();
  161.         return 1;
  162.     }
  163.  
  164.     return 0;
  165. }
  166.  
  167.  
  168.  
  169. /*************************************
  170.  *
  171.  *    Video system shutdown
  172.  *
  173.  *************************************/
  174.  
  175. void eprom_vh_stop(void)
  176. {
  177.     atarigen_pf_free();
  178.     atarigen_mo_free();
  179. }
  180.  
  181.  
  182.  
  183. /*************************************
  184.  *
  185.  *    Playfield RAM write handler
  186.  *
  187.  *************************************/
  188.  
  189. WRITE_HANDLER( eprom_playfieldram_w )
  190. {
  191.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  192.     int newword = COMBINE_WORD(oldword, data);
  193.  
  194.     if (oldword != newword)
  195.     {
  196.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  197.         atarigen_pf_dirty[offset / 2] = 1;
  198.     }
  199. }
  200.  
  201.  
  202.  
  203. /*************************************
  204.  *
  205.  *    Playfield palette RAM write handler
  206.  *
  207.  *************************************/
  208.  
  209. WRITE_HANDLER( eprom_playfieldpalram_w )
  210. {
  211.     int oldword = READ_WORD(&eprom_playfieldpalram[offset]);
  212.     int newword = COMBINE_WORD(oldword, data);
  213.  
  214.     if (oldword != newword)
  215.     {
  216.         WRITE_WORD(&eprom_playfieldpalram[offset], newword);
  217.         atarigen_pf_dirty[offset / 2] = 1;
  218.     }
  219. }
  220.  
  221.  
  222.  
  223. /*************************************
  224.  *
  225.  *    Periodic scanline updater
  226.  *
  227.  *************************************/
  228.  
  229. void eprom_scanline_update(int scanline)
  230. {
  231.     /* update the playfield */
  232.     if (scanline == 0)
  233.     {
  234.         pf_state.hscroll = (READ_WORD(&atarigen_alpharam[0xf00]) >> 7) & 0x1ff;
  235.         pf_state.vscroll = (READ_WORD(&atarigen_alpharam[0xf02]) >> 7) & 0x1ff;
  236.         atarigen_pf_update(&pf_state, scanline);
  237.     }
  238.  
  239.     /* update the MOs from the SLIP table */
  240.     atarigen_mo_update_slip_512(atarigen_spriteram, pf_state.vscroll, scanline, &atarigen_alpharam[0xf80]);
  241. }
  242.  
  243.  
  244.  
  245. /*************************************
  246.  *
  247.  *    Main refresh
  248.  *
  249.  *************************************/
  250.  
  251. void eprom_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  252. {
  253.     int i;
  254.  
  255. #if DEBUG_VIDEO
  256.     debug();
  257. #endif
  258.  
  259.     /* update the palette */
  260.     if (update_palette())
  261.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 2);
  262.  
  263.     /* set up the all-transparent overrender palette */
  264.     for (i = 0; i < 16; i++)
  265.         atarigen_overrender_colortable[i] = palette_transparent_pen;
  266.  
  267.     /* render the playfield */
  268.     memset(atarigen_pf_visit, 0, 64*64);
  269.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  270.  
  271.     /* render the motion objects */
  272.     atarigen_mo_process(mo_render_callback, bitmap);
  273.  
  274.     /* redraw the alpha layer completely */
  275.     {
  276.         const struct GfxElement *gfx = Machine->gfx[1];
  277.         int sx, sy, offs;
  278.  
  279.         for (sy = 0; sy < YCHARS; sy++)
  280.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  281.             {
  282.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  283.                 int code = data & 0x3ff;
  284.                 int opaque = data & 0x8000;
  285.  
  286.                 if (code || opaque)
  287.                 {
  288.                     int color = ((data >> 10) & 0xf) | ((data >> 9) & 0x20);
  289.                     drawgfx(bitmap, gfx, code, color, 0, 0, 8 * sx, 8 * sy, 0,
  290.                             opaque ? TRANSPARENCY_NONE : TRANSPARENCY_PEN, 0);
  291.                 }
  292.             }
  293.     }
  294.  
  295.     /* update onscreen messages */
  296.     atarigen_update_messages();
  297. }
  298.  
  299.  
  300.  
  301. /*************************************
  302.  *
  303.  *    Palette management
  304.  *
  305.  *************************************/
  306.  
  307. static const UINT8 *update_palette(void)
  308. {
  309.     UINT16 mo_map[16], al_map[64], pf_map[16];
  310.     int i, j;
  311.  
  312.     /* reset color tracking */
  313.     memset(mo_map, 0, sizeof(mo_map));
  314.     memset(pf_map, 0, sizeof(pf_map));
  315.     memset(al_map, 0, sizeof(al_map));
  316.     palette_init_used_colors();
  317.  
  318.     /* update color usage for the playfield */
  319.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  320.  
  321.     /* update color usage for the mo's */
  322.     atarigen_mo_process(mo_color_callback, mo_map);
  323.  
  324.     /* update color usage for the alphanumerics */
  325.     {
  326.         const unsigned int *usage = Machine->gfx[1]->pen_usage;
  327.         int sx, sy, offs;
  328.  
  329.         for (sy = 0; sy < YCHARS; sy++)
  330.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  331.             {
  332.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  333.                 int color = ((data >> 10) & 0xf) | ((data >> 9) & 0x20);
  334.                 int code = data & 0x3ff;
  335.  
  336.                 al_map[color] |= usage[code];
  337.             }
  338.     }
  339.  
  340.     /* rebuild the playfield palette */
  341.     for (i = 0; i < 16; i++)
  342.     {
  343.         UINT16 used = pf_map[i];
  344.         if (used)
  345.             for (j = 0; j < 16; j++)
  346.                 if (used & (1 << j))
  347.                     palette_used_colors[0x200 + i * 16 + j] = PALETTE_COLOR_USED;
  348.     }
  349.  
  350.     /* rebuild the motion object palette */
  351.     for (i = 0; i < 16; i++)
  352.     {
  353.         UINT16 used = mo_map[i];
  354.         if (used)
  355.         {
  356.             palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  357.             for (j = 1; j < 16; j++)
  358.                 if (used & (1 << j))
  359.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  360.         }
  361.     }
  362.  
  363.     /* rebuild the alphanumerics palette */
  364.     for (i = 0; i < 64; i++)
  365.     {
  366.         UINT16 used = al_map[i];
  367.         if (used)
  368.             for (j = 0; j < 4; j++)
  369.                 if (used & (1 << j))
  370.                     palette_used_colors[0x000 + i * 4 + j] = PALETTE_COLOR_USED;
  371.     }
  372.  
  373.     return palette_recalc();
  374. }
  375.  
  376.  
  377.  
  378. /*************************************
  379.  *
  380.  *    Playfield palette
  381.  *
  382.  *************************************/
  383.  
  384. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  385. {
  386.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  387.     UINT16 *colormap = param;
  388.     int x, y;
  389.  
  390.     /* standard loop over tiles */
  391.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  392.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  393.         {
  394.             int offs = x * 64 + y;
  395.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  396.             int data2 = READ_WORD(&eprom_playfieldpalram[offs * 2]);
  397.             int code = data1 & 0x7fff;
  398.             int color = (data2 >> 8) & 15;
  399.  
  400.             /* mark the colors used by this tile */
  401.             colormap[color] |= usage[code];
  402.  
  403.             /* also mark unvisited tiles dirty */
  404.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 1;
  405.         }
  406. }
  407.  
  408.  
  409.  
  410. /*************************************
  411.  *
  412.  *    Playfield rendering
  413.  *
  414.  *************************************/
  415.  
  416. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  417. {
  418.     const struct GfxElement *gfx = Machine->gfx[0];
  419.     struct osd_bitmap *bitmap = param;
  420.     int x, y;
  421.  
  422.     /* standard loop over tiles */
  423.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  424.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  425.         {
  426.             int offs = x * 64 + y;
  427.  
  428.             /* update only if dirty */
  429.             if (atarigen_pf_dirty[offs])
  430.             {
  431.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  432.                 int data2 = READ_WORD(&eprom_playfieldpalram[offs * 2]);
  433.                 int color = (data2 >> 8) & 15;
  434.                 int code = data1 & 0x7fff;
  435.                 int hflip = data1 & 0x8000;
  436.  
  437.                 drawgfx(atarigen_pf_bitmap, gfx, code, 0x10 + color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  438.                 atarigen_pf_dirty[offs] = 0;
  439.  
  440. #if DEBUG_VIDEO
  441.                 if (show_colors)
  442.                 {
  443.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  444.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  445.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  446.                 }
  447. #endif
  448.             }
  449.  
  450.             /* track the tiles we've visited */
  451.             atarigen_pf_visit[offs] = 1;
  452.         }
  453.  
  454.     /* then blast the result */
  455.     x = -state->hscroll;
  456.     y = -state->vscroll;
  457.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  458. }
  459.  
  460.  
  461.  
  462. /*************************************
  463.  *
  464.  *    Playfield overrendering
  465.  *
  466.  *************************************/
  467.  
  468. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  469. {
  470.     const struct pf_overrender_data *overrender_data = param;
  471.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  472.     const struct GfxElement *gfx = Machine->gfx[0];
  473.     int x, y;
  474.  
  475.     /* standard loop over tiles */
  476.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  477.     {
  478.         int sx = (8 * x - state->hscroll) & 0x1ff;
  479.         if (sx >= XDIM) sx -= 0x200;
  480.  
  481.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  482.         {
  483.             int offs = x * 64 + y;
  484.             int data2 = READ_WORD(&eprom_playfieldpalram[offs * 2]);
  485.             int color = (data2 >> 8) & 15;
  486.             int sy = (8 * y - state->vscroll) & 0x1ff;
  487.             if (sy >= YDIM) sy -= 0x200;
  488.  
  489.             /* update only if dirty */
  490.             if (color >= 13 + overrender_data->mo_priority)
  491.             {
  492.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  493.                 int code = data1 & 0x7fff;
  494.                 int hflip = data1 & 0x8000;
  495.  
  496.                 drawgfx(bitmap, gfx, code, 0x10 + color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, 0xff00);
  497.  
  498. #if DEBUG_VIDEO
  499.                 if (show_colors)
  500.                 {
  501.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, sx + 0, sy, 0, TRANSPARENCY_PEN, 0);
  502.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, sx + 2, sy, 0, TRANSPARENCY_PEN, 0);
  503.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 0, 0, 0, sx + 1, sy, 0, TRANSPARENCY_PEN, 0);
  504.                 }
  505. #endif
  506.             }
  507.         }
  508.     }
  509. }
  510.  
  511.  
  512.  
  513. /*************************************
  514.  *
  515.  *    Motion object palette
  516.  *
  517.  *************************************/
  518.  
  519. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  520. {
  521.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  522.     UINT16 *colormap = param;
  523.     int code = data[1] & 0x7fff;
  524.     int color = data[2] & 0x000f;
  525.     int hsize = ((data[3] >> 4) & 7) + 1;
  526.     int vsize = (data[3] & 7) + 1;
  527.     int tiles = hsize * vsize;
  528.     UINT16 temp = 0;
  529.     int i;
  530.  
  531.     for (i = 0; i < tiles; i++)
  532.         temp |= usage[code++];
  533.     colormap[color] |= temp;
  534. }
  535.  
  536.  
  537.  
  538. /*************************************
  539.  *
  540.  *    Motion object rendering
  541.  *
  542.  *************************************/
  543.  
  544. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  545. {
  546.     struct GfxElement *gfx = Machine->gfx[0];
  547.     struct pf_overrender_data overrender_data;
  548.     struct osd_bitmap *bitmap = param;
  549.     struct rectangle pf_clip;
  550.  
  551.     /* extract data from the various words */
  552.     int code = data[1] & 0x7fff;
  553.     int xpos = (data[2] >> 7) - pf_state.hscroll;
  554.     int priority = (data[2] >> 4) & 3;
  555.     int color = data[2] & 0x000f;
  556.     int ypos = -(data[3] >> 7) - pf_state.vscroll;
  557.     int hsize = ((data[3] >> 4) & 7) + 1;
  558.     int hflip = data[3] & 0x0008;
  559.     int vsize = (data[3] & 7) + 1;
  560.  
  561.     /* adjust for height */
  562.     ypos -= vsize * 8;
  563.  
  564.     /* adjust the final coordinates */
  565.     xpos &= 0x1ff;
  566.     ypos &= 0x1ff;
  567.     if (xpos >= XDIM) xpos -= 0x200;
  568.     if (ypos >= YDIM) ypos -= 0x200;
  569.  
  570.     /* determine the bounding box */
  571.     atarigen_mo_compute_clip_8x8(pf_clip, xpos, ypos, hsize, vsize, clip);
  572.  
  573.     /* simple case? */
  574.     if (priority == 3)
  575.     {
  576.         /* just draw -- we have dominion over all */
  577.         atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  578.     }
  579.  
  580.     /* otherwise, it gets a smidge trickier */
  581.     else
  582.     {
  583.         /* draw an instance of the object in all transparent pens */
  584.         atarigen_mo_draw_transparent_8x8(bitmap, gfx, code, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  585.  
  586.         /* and then draw it normally on the temp bitmap */
  587.         atarigen_mo_draw_8x8(atarigen_pf_overrender_bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_NONE, 0);
  588.  
  589.         /* overrender the playfield on top of that that */
  590.         overrender_data.mo_priority = priority;
  591.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  592.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  593.  
  594.         /* finally, copy this chunk to the real bitmap */
  595.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  596.     }
  597.  
  598. #if DEBUG_VIDEO
  599.     if (show_colors)
  600.     {
  601.         int tx = (pf_clip.min_x + pf_clip.max_x) / 2 - 3;
  602.         int ty = (pf_clip.min_y + pf_clip.max_y) / 2 - 4;
  603.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  604.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  605.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  606.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  607.         drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[priority], 0, 0, 0, tx, ty, 0, TRANSPARENCY_NONE, 0);
  608.     }
  609. #endif
  610. }
  611.  
  612.  
  613.  
  614. /*************************************
  615.  *
  616.  *    Debugging
  617.  *
  618.  *************************************/
  619.  
  620. #if DEBUG_VIDEO
  621.  
  622. static void debug(void)
  623. {
  624.     int new_show_colors;
  625.  
  626.     new_show_colors = keyboard_pressed(KEYCODE_CAPSLOCK);
  627.     if (new_show_colors != show_colors)
  628.     {
  629.         show_colors = new_show_colors;
  630.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  631.     }
  632.  
  633.     special_pen = -1;
  634.     if (keyboard_pressed(KEYCODE_Q)) special_pen = 0;
  635.     if (keyboard_pressed(KEYCODE_W)) special_pen = 1;
  636.     if (keyboard_pressed(KEYCODE_E)) special_pen = 2;
  637.     if (keyboard_pressed(KEYCODE_R)) special_pen = 3;
  638.     if (keyboard_pressed(KEYCODE_T)) special_pen = 4;
  639.     if (keyboard_pressed(KEYCODE_Y)) special_pen = 5;
  640.     if (keyboard_pressed(KEYCODE_U)) special_pen = 6;
  641.     if (keyboard_pressed(KEYCODE_I)) special_pen = 7;
  642.  
  643.     if (keyboard_pressed(KEYCODE_A)) special_pen = 8;
  644.     if (keyboard_pressed(KEYCODE_S)) special_pen = 9;
  645.     if (keyboard_pressed(KEYCODE_D)) special_pen = 10;
  646.     if (keyboard_pressed(KEYCODE_F)) special_pen = 11;
  647.     if (keyboard_pressed(KEYCODE_G)) special_pen = 12;
  648.     if (keyboard_pressed(KEYCODE_H)) special_pen = 13;
  649.     if (keyboard_pressed(KEYCODE_J)) special_pen = 14;
  650.     if (keyboard_pressed(KEYCODE_K)) special_pen = 15;
  651.  
  652.     if (keyboard_pressed(KEYCODE_9))
  653.     {
  654.         static int count;
  655.         char name[50];
  656.         FILE *f;
  657.         int i;
  658.  
  659.         while (keyboard_pressed(KEYCODE_9)) { }
  660.  
  661.         sprintf(name, "Dump %d", ++count);
  662.         f = fopen(name, "wt");
  663.  
  664.         fprintf(f, "\n\nAlpha Palette:\n");
  665.         for (i = 0x000; i < 0x100; i++)
  666.         {
  667.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  668.             if ((i & 15) == 15) fprintf(f, "\n");
  669.         }
  670.  
  671.         fprintf(f, "\n\nMotion Object Palette:\n");
  672.         for (i = 0x100; i < 0x200; i++)
  673.         {
  674.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  675.             if ((i & 15) == 15) fprintf(f, "\n");
  676.         }
  677.  
  678.         fprintf(f, "\n\nPlayfield Palette:\n");
  679.         for (i = 0x200; i < 0x400; i++)
  680.         {
  681.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  682.             if ((i & 15) == 15) fprintf(f, "\n");
  683.         }
  684.  
  685.         fprintf(f, "\n\nMotion Object Config:\n");
  686.         for (i = 0x00; i < 0x40; i++)
  687.         {
  688.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[0xf00 + i*2]));
  689.             if ((i & 15) == 15) fprintf(f, "\n");
  690.         }
  691.  
  692.         fprintf(f, "\n\nMotion Object SLIPs:\n");
  693.         for (i = 0x00; i < 0x40; i++)
  694.         {
  695.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[0xf80 + i*2]));
  696.             if ((i & 15) == 15) fprintf(f, "\n");
  697.         }
  698.  
  699.         fprintf(f, "\n\nMotion Objects\n");
  700.         for (i = 0; i < 0x400; i++)
  701.         {
  702.             UINT16 *data = (UINT16 *)&atarigen_spriteram[i*8];
  703.             int code = data[1] & 0x7fff;
  704.             int hsize = ((data[3] >> 4) & 7) + 1;
  705.             int vsize = (data[3] & 7) + 1;
  706.             int xpos = (data[2] >> 7);
  707.             int ypos = (data[3] >> 7) - vsize * 8;
  708.             int color = data[2] & 15;
  709.             int hflip = data[3] & 0x0008;
  710.             fprintf(f, "   Object %03X: L=%03X P=%04X C=%X X=%03X Y=%03X W=%d H=%d F=%d LEFT=(%04X %04X %04X %04X)\n",
  711.                     i, data[0] & 0x3ff, code, color, xpos & 0x1ff, ypos & 0x1ff, hsize, vsize, hflip,
  712.                     data[0] & 0xfc00, data[1] & 0x0000, data[2] & 0x0070, data[3] & 0x0000);
  713.         }
  714.  
  715.         fprintf(f, "\n\nPlayfield dump\n");
  716.         for (i = 0; i < atarigen_playfieldram_size / 2; i++)
  717.         {
  718.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[i*2]));
  719.             if ((i & 63) == 63) fprintf(f, "\n");
  720.         }
  721.  
  722.         fclose(f);
  723.     }
  724. }
  725.  
  726. #endif
  727.